package jch.learn.java.advanced.chapter1_stream.collecting;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

// 将结果收集到map中
public class CollectingIntoMaps {

    public static class Person {
        private int id;
        private String name;

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public Person(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public String toString() {
            return getClass().getName() + "[id=" + id + ",name=" + name + "]";
        }
    }

    public static Stream<Person> people() {
        return Stream.of(new Person(1001, "Peter"), new Person(1002, "Paul"), new Person(1003, "Mary"));
    }


    public static void main(String[] args) {

        // java.util.stream.Collector

        // static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,Function<? super T, ? extends U> valueMapper)
        // 产生一个映射表HashMap。keyMapper和valueMapper函数会应用于每个收集的元素上，从而在所产生的映射表中产生一个键/值。默认情况下，当两个元素产生相同的键时，会抛出一个IllegalStateException异常。
        Map<Integer, String> idToName = people().collect(Collectors.toMap(Person::getId, Person::getName));
        System.out.println("idToName: " + idToName);

        Map<Integer, Person> idToPerson = people().collect(Collectors.toMap(Person::getId, Function.identity()));
        System.out.println("idToPerson: " + idToPerson.getClass().getName() + idToPerson);

        // static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,Function<? super T,? extends U> valueMapper,BinaryOperator<U> mergeFunction)
        // 产生一个映射表HashMap，keyMapper和valueMapper函数会应用于每个收集的元素上，mergeFunction函数用于合并具有相同键的值。

        // static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap<Function<? super T,? extends K> keyMapper,Function<? super T,? extends U> valueMapper,BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
        // 产生一个映射表HashMap，keyMapper和valueMapper函数会应用于每个收集的元素上，mergeFunction函数用于合并具有相同键的值, mapSupplier产生所期望的映射表实例。
        idToPerson = people().collect(Collectors.toMap(Person::getId, Function.identity(), (existingValue, newValue) -> {
            throw new IllegalStateException();
        }, TreeMap::new));
        System.out.println("idToPerson: " + idToPerson.getClass().getName() + idToPerson);
        Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
        Map<String, String> languageNames = locales.collect(Collectors.toMap(Locale::getDisplayLanguage, l -> l.getDisplayLanguage(), (existingValue, newValue) -> existingValue));
        System.out.println("languageNames: " + languageNames);

        locales = Stream.of(Locale.getAvailableLocales());
        Map<String, Set<String>> countryLanguageSets = locales.collect(Collectors.toMap(Locale::getDisplayCountry, l -> Collections.singleton(l.getDisplayLanguage()), (a, b) -> {
            Set<String> union = new HashSet<>(a);
            union.addAll(b);
            return union;
        }));
        System.out.println("countryLanguageSets: " + countryLanguageSets);

        // static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper,Function<? super T,? extends U> valueMapper)
        // static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper,Function<? super T,? extends U> valueMapper,BinaryOperator<U> mergeFunction)
        // static <T,K,U,M extends ConcurrentMap<K,U>> Collector<T,?,M> toConcurrentMap<Function<? super T,? extends K> keyMapper,Function<? super T,? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier)
        // 产生一个并发映射表ConcurrentHashMap，mergeFunction函数合并处理相同的值，mapSupplier用于产生所期望的映射表实例。
    }
}
